/*
 * This file is part of the Sx Framework Library.
 * 
 * Copyright (C) 2013 University of Colorado Denver
 * <min.choi@ucdenver.edu> <shane.transue@ucdenver.edu>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 */
#ifndef SX_VIEWPORT_CONTROLLER_H
#define SX_VIEWPORT_CONTROLLER_H

/* Parent Include */
#include <sxController.h>

#include <sxMouse.h>
#include <sxRenderable.h>
#include <sxMath.h>
#include <sxColor3.h>
#include <sxColor4.h>
#include <sxString.h>

namespace Sx {
namespace Interface {

class Viewport;

class ViewportController : public Controller<Viewport>, public Renderable {
public:
	ViewportController(Viewport* viewport);
	virtual ~ViewportController();

	/*
	 * The initialize function is utilized to initialize components of a 
	 * viewport that either require external resources or a one-time creation
	 * for use by this controller. Ownership not taken. The caller must properly
	 * handle the memory for the context object.
	 */
	virtual bool initialize();

	/* The update function should always be called before the render function */
	virtual void update(float dt) = 0;

	/* Render the components of the viewport controller. */
	virtual void render() const = 0;

	/* Perform any pre or post rendering operations. */
	virtual bool preRender() const;
	virtual bool postRender() const;

	/* Standard Resize function */
	virtual void resize(int width, int height) = 0;

	/* Provides an interface for handling mouse based input events. */
	virtual void mousePressEvent(int x, int y, MouseButton button, ModifierKey modifierKey) = 0;
	virtual void mouseReleaseEvent(int x, int y, MouseButton button, ModifierKey modifierKey) = 0;
	virtual void mouseClickEvent(int x, int y, MouseButton button, ModifierKey modifierKey) = 0;
	virtual void mouseMoveEvent(int x, int y, MouseButton button, ModifierKey modifierKey) = 0;
	virtual void mouseWheelEvent(int delta) = 0;
	virtual void mouseEnterEvent() = 0;
	virtual void mouseExitEvent() = 0;

	/* The following set of functions set the clear color of this Viewport. */
	void setClearColor(float r, float g, float b);
	void setClearColor(float r, float g, float b, float a);
	void setClearColor(const Graphics::Color3f& color);
	void setClearColor(const Graphics::Color4f& color);

	/*
	 * The following functions set the color of any text rendered in this
	 * viewport.
	 */
	void setTextColor(float r, float g, float b);
	void setTextColor(float r, float g, float b, float a);
	void setTextColor(const Graphics::Color3f& color);
	void setTextColor(const Graphics::Color4f& color);

	/*
	 * The following functions set the color of this Viewports border based
	 * on whether or not it is selected (has focus).
	 */
	void setBorderColor(float r, float g, float b, bool selected = false);
	void setBorderColor(float r, float g, float b, float a, bool selected = false);
	void setBorderColor(const Graphics::Color3f& color, bool selected = false);
	void setBorderColor(const Graphics::Color4f& color, bool selected = false);

	/*
	 * Sets the title text of this viewport. The title text of a viewport is
	 * displayed in the upper left hand corner of the viewports render area.
	 */
	void setText(const String& text);

	/*
	 * Sets this viewport as active. Generally this is associated with a
	 * viewport gaining focus.
	 */
	void setSelected(bool selected);
	void select();
	void deselect();

	void setPaused(bool paused);
	void pause();
	void resume();

	void setInputEnabled(bool enabled);
	void enableInput();
	void disableInput();

	/*
	 * Sets the width of the controlled viewports border. Set this value to 0.0f
	 * make the viewport have no border.
	 */
	void setBorderWidth(unsigned int width);

	/* Returns the title text visible in this Viewport. */
	String getText() const;

	/* Returns the clear color of this Viewport. */
	Graphics::Color4f getClearColor() const;

	/* Returns the color of the title text of this viewport. */
	Graphics::Color4f getTextColor() const;

	/* Returns both border colors (selected and unselected). */
	Graphics::Color4f getBorderColor(bool selected = false);

	/*
	 * If this ViewportController is selected then this function will return 
	 * true. Selected is generally synonymous with the controlled Viewport
	 * having keyboard focus.
	 */
	bool isSelected() const;
	bool isInitialized() const;
	bool isPaused() const;
	bool isInputEnabled() const;
	bool isInEdit() const;

	void incrementFrameIndex();
	void setFrameIndex(unsigned int index);
	void resetFrameIndex();
	void clearFrameIndex();

	void setMouseCurrentPosition(int x, int y);
	void setMousePressPosition(int x, int y);
	void setMouseReleasePosition(int x, int y);
	void setMousePositionDifference(int x, int y);
	void setMousePositionDifference(const Eigen::Vector2i& positionDisplacement);
	void updateMouseLastPosition();
	void updateMousePositionDifference();

protected:
	/*
	 * Viewports can have a border for selection purposes. Mainly this lets the
	 * user know what viewport is selected for keyboard focus. To make a
	 * viewport have no border, simply set this size to 0.0f.
	 */
	unsigned int borderWidth;

	/* Interface Colors */
	Graphics::Color4f clearColor;
	Graphics::Color4f textColor;
	Graphics::Color4f textColorSelected;
	Graphics::Color4f borderColor;
	Graphics::Color4f borderColorSelected;

	/* Every viewport has a text title for identification. */
	String text;

	/*
	 * Any components that are part of the 2D user interface of a viewport
	 * controller can be hidden.
	 */
	bool displayUI, displayText;

	/*
	 * When a viewport is selected or active its appearance may change to
	 * indicate to the user that this controller will receive the input
	 * commands.
	 */
	bool selected;

	/* 
	 * When a controller contains functionality that should not be interfered
	 * with by the user, this bool can be used to prevent the user from
	 * providing input.
	 */
	bool inputEnabled;
	bool inEdit;

	/* When a viewport is paused, all update functions should be suspended. */
	bool paused;

	/* Index of the current rendered frame. This also acts as a frame counter */
	unsigned int frameIndex;

	/* Flag for the initialized state of this controller. */
	bool initialized;

	/*
	 * Mouse based tracking. These are utilized for keeping track of the
	 * cursor position for drag movements.
	 */
	Eigen::Vector2i positionDifference;
	Eigen::Vector2i mousePosCur, mousePosLast;
	Eigen::Vector2i mousePosPress, mousePosRelease;
};

}

}

#endif
